<template>
	<div id="PrintTxt">
		<div class="typing-container">
			<!-- 使用 ref 绑定 DOM 元素 -->
			<p ref="typingTextRef">{{ typedText }}</p>
			<!-- 动态绑定 class，控制光标闪烁 -->
			<span class="cursor" :class="{ blink: cursorBlink }"></span>
		</div>
		<!-- 添加一个加载/错误状态显示 (可选) -->
		<div v-if="isLoading" class="status-message">正在加载文本...</div>
		<div v-if="fetchError" class="status-message error">{{ fetchError }}</div>
	</div>
</template>

<script setup>
	// --- 依赖引入 ---
	import {
		ref,
		onMounted,
		onUnmounted,
		nextTick
	} from 'vue';
	// 引入 axios 用于网络请求
	import axios from 'axios';

	// --- 响应式状态定义 ---

	// 存储从 API 获取的原始文本数组
	const originalTexts = ref([]);
	// 存储当前循环中待显示的随机排序文本
	const textsToDisplay = ref([]);
	// 当前显示在屏幕上的打字文本
	const typedText = ref("");
	// 控制光标是否处于闪烁状态（CSS 动画处理）
	const cursorBlink = ref(true);
	// 当前正在处理的字符在当前文本中的索引
	const charIndex = ref(0);
	// 每个字符打出/删除的时间间隔（毫秒）
	const typingInterval = ref(300); // 打字速度
	const deletingInterval = ref(150); // 删除速度 (可以设置不同)
	const pauseDuration = ref(3000); // 打完字后的停顿时间 (毫秒)
	// 是否处于删除文字阶段
	const isDeleting = ref(false);
	// 当前正在处理的完整文本
	const currentText = ref("");
	// 用于存储打字停顿定时器的 ID
	const pauseTimer = ref(null);
	// 用于存储主打字/删除循环定时器的 ID
	const typingTimer = ref(null);
	// 用于引用 <p> 元素 (虽然没直接用，但保留可能有用)
	const typingTextRef = ref(null);
	// API 加载状态
	const isLoading = ref(true); // 初始为 true，表示正在加载
	// API 请求错误信息
	const fetchError = ref(null);

	// --- 工具函数 ---

	/**
	 * @description Fisher-Yates (Knuth) 随机打乱数组算法
	 * @param {Array} array - 需要打乱的数组
	 * @returns {Array} - 打乱后的新数组 (不修改原数组)
	 */
	const shuffleArray = (array) => {
		const shuffled = [...array]; // 创建副本，避免修改原数组
		for (let i = shuffled.length - 1; i > 0; i--) {
			const j = Math.floor(Math.random() * (i + 1));
			[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; // ES6 解构赋值交换元素
		}
		return shuffled;
	};


	// --- 核心逻辑方法 ---

	// 处理打字或删除的核心逻辑
	const typeOrDelete = () => {
		// 根据当前是打字还是删除，选择不同的速度
		const interval = isDeleting.value ? deletingInterval.value : typingInterval.value;

		// 清除旧的定时器（如果存在）
		if (typingTimer.value) {
			clearInterval(typingTimer.value);
			typingTimer.value = null; // 重置引用
		}

		// 启动新的定时器
		typingTimer.value = setInterval(() => {
			performStep(); // 执行单步操作
		}, interval);
	};

	// 执行单步打字或删除操作
	const performStep = async () => { // 改为 async 以便使用 nextTick
		if (isDeleting.value) {
			// --- 删除阶段 ---
			if (charIndex.value > 0) {
				// 如果还有字符可删，则删除最后一个字符
				typedText.value = currentText.value.slice(0, charIndex.value - 1);
				charIndex.value--;
			} else {
				// --- 删除完毕 ---
				// 当前文本已全部删除 (charIndex 为 0)
				isDeleting.value = false;
				// 切换到下一段文本 (会重新启动定时器)
				await nextText();
			}
		} else {
			// --- 打字阶段 ---
			const currentTextLength = currentText.value.length;
			if (charIndex.value < currentTextLength) {
				// 如果还有字符要打，则添加下一个字符
				typedText.value += currentText.value.charAt(charIndex.value);
				charIndex.value++;
			} else {
				// --- 打字完毕 ---
				// 当前文本已全部打完 (charIndex 等于文本长度)
				// 清除当前打字/删除定时器，准备停顿
				if (typingTimer.value) {
					clearInterval(typingTimer.value);
					typingTimer.value = null;
				}
				// 设置停顿定时器
				// console.log("打字完毕，开始停顿..."); // 调试信息
				pauseTimer.value = setTimeout(() => {
					// console.log("停顿结束，准备删除..."); // 调试信息
					isDeleting.value = true; // 切换到删除状态
					clearTimeout(pauseTimer.value); // 清除已完成的定时器 ID
					pauseTimer.value = null; // 重置定时器 ID 引用
					typeOrDelete(); // 停顿结束后开始删除 (会设置删除的 interval)
				}, pauseDuration.value);
			}
		}
	};

	// 切换到下一个文本
	const nextText = async () => {
        // console.log("准备切换文本，当前 textsToDisplay:", textsToDisplay.value); // 调试信息

        // 从待显示列表中移除刚刚处理完的文本 (它在 currentText 中)
        // 我们假设 currentText 总是 textsToDisplay 的第一个元素
        if (textsToDisplay.value.length > 0) {
            textsToDisplay.value.shift(); // 移除第一个元素
        }

		// 检查待显示列表是否为空
		if (textsToDisplay.value.length === 0) {
			// console.log("当前循环结束，重新洗牌..."); // 调试信息
			// 如果为空，表示当前循环已显示完所有文本，重新洗牌
			if (originalTexts.value.length > 0) {
				textsToDisplay.value = shuffleArray(originalTexts.value);
                // console.log("重新洗牌后:", textsToDisplay.value); // 调试信息
			} else {
				// 如果原始数据就为空，则停止，或者显示提示
				console.warn("没有可显示的文本了。");
				clearAllTimers(); // 清除所有定时器停止动画
                fetchError.value = "没有可显示的文本。"; // 可以显示一个提示
				return; // 结束处理
			}
		}

		// 获取下一个要显示的文本 (洗牌后的第一个)
		currentText.value = textsToDisplay.value[0];
		// 重置字符索引和已显示文本
		charIndex.value = 0;
		typedText.value = "";
        isDeleting.value = false; // 确保是从打字开始

		// 等待 DOM 更新（虽然 typedText 清空了，但保险起见）
		await nextTick();

		// 开始处理新的文本（打字）
		typeOrDelete();
	};

	// 清除所有定时器
	const clearAllTimers = () => {
		if (typingTimer.value) {
			clearInterval(typingTimer.value);
			typingTimer.value = null;
		}
		if (pauseTimer.value) {
			clearTimeout(pauseTimer.value);
			pauseTimer.value = null;
		}
        // 如果有 JS 控制的光标闪烁定时器，也在这里清除
		// if (blinkTimer.value) {
		//     clearInterval(blinkTimer.value);
		//     blinkTimer.value = null;
		// }
	};

	// --- 生命周期钩子 ---

	// 组件挂载后执行
	onMounted(async () => {
		isLoading.value = true; // 开始加载
		fetchError.value = null; // 清除旧错误
		try {
			// 发起 GET 请求
			const response = await axios.get('/api/official/selectall');

			// 检查响应数据结构是否符合预期
			if (response.data && Array.isArray(response.data.data) && response.data.data.length > 0) {
				// 提取 txt 字段到 originalTexts
				originalTexts.value = response.data.data.map(item => item.txt);
				// console.log("获取到的原始文本:", originalTexts.value); // 调试信息

				// 初始化待显示列表 (首次随机打乱)
				textsToDisplay.value = shuffleArray(originalTexts.value);
				// console.log("首次洗牌后待显示:", textsToDisplay.value); // 调试信息

				// 设置第一个要显示的文本
				currentText.value = textsToDisplay.value[0];

				// 等待 DOM 更新后再开始打字
				await nextTick();

				// 开始打字循环
				typeOrDelete();

			} else {
				// API 返回的数据为空或格式不正确
				console.error("API 返回数据格式错误或为空:", response.data);
				fetchError.value = "加载文本失败：数据格式错误或为空。";
                // 可以设置一个默认的文本
                originalTexts.value = ["加载失败，请稍后重试..."];
                textsToDisplay.value = [...originalTexts.value];
                currentText.value = textsToDisplay.value[0];
                await nextTick();
				typeOrDelete(); // 尝试显示错误信息
			}
		} catch (error) {
			// 处理请求错误
			console.error("请求 API 出错:", error);
			fetchError.value = `加载文本失败：${error.message || '网络错误'}`;
            // 可以设置一个默认的文本
            originalTexts.value = ["加载失败，请检查网络连接..."];
            textsToDisplay.value = [...originalTexts.value];
            currentText.value = textsToDisplay.value[0];
            await nextTick();
			typeOrDelete(); // 尝试显示错误信息

		} finally {
			isLoading.value = false; // 加载完成（无论成功或失败）
		}
	});

	// 组件卸载前执行
	onUnmounted(() => {
		console.log("组件卸载，清除所有定时器..."); // 调试信息
		// 清除所有定时器，防止内存泄漏
		clearAllTimers();
	});
</script>

<style lang="scss" scoped>
	/* 全局重置样式 - 修正 font-weight */
	* {
		margin: 0px;
		padding: 0px;
		border: none;
		border-radius: 0px;
		font-size: 14px;
		/* font-weight: 300px; <-- 错误：font-weight 没有 px 单位 */
		font-weight: 300;
		/* 推荐添加 */
		box-sizing: border-box;
	}

	#PrintTxt {
		/* 可以给外层容器一些样式，例如定位 */
		position: relative; /* 或根据需要调整 */
		display: flex; /* 用于居中或其他布局 */
		justify-content: center; /* 示例居中 */
		align-items: center; /* 示例居中 */
		/* height: 100px; */ /* 示例高度 */
		/* background-color: #222; */ /* 示例背景 */
		padding: 20px;
	}

	.typing-container {
		/* height: 50px; */ /* 让内容自动撑开高度，或者设置 min-height */
		min-height: 50px; /* 最小高度 */
		line-height: 50px; /* 如果想垂直居中文本，可以使用 line-height 等于 height/min-height */
		display: inline-block; /* 或者 block/flex 根据布局需要 */
		position: relative; /* 为了光标的绝对定位 */
		color: var(--primary-color); /* 文本颜色 */
		// color: #05f900;
		background-color: rgba(0, 0, 0, 0.3); /* 使用 rgba 添加半透明背景 */
		backdrop-filter: blur(5px); /* 毛玻璃效果 */
		border-radius: 20px; /* 圆角 */
		padding: 0 40px 0 20px; /* 调整内边距，给光标留出空间 (右侧40px) */
		box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); /* 阴影 */
		white-space: nowrap; /* 防止打字时文本换行 */
		overflow: hidden; /* 隐藏可能溢出的内容 */
		max-width: 90%; /* 防止过长文本撑破布局 */
	}

	/* p 标签样式 */
	.typing-container p {
		display: inline; /* 让 p 标签适应内容宽度 */
		margin: 0; /* 移除默认 margin */
		padding: 0; /* 移除默认 padding */
		font-size: 18px; /* 调整字体大小 */
		vertical-align: middle; /* 尝试垂直对齐 */
		color: var(--primary-color); /* 文本颜色 */
	}


	.cursor {
		position: absolute; /* 相对于 .typing-container 定位 */
		/* top: 12px; */ /* 使用 top/bottom/transform 实现垂直居中 */
		top: 55%; /* 初始定位到中间 */
		transform: translateY(-50%); /* 向上移动自身高度的一半实现垂直居中 */
		right: 15px; /* 距离右侧的距离 */
		width: 3px; /* 光标宽度 */
		height: 24px; /* 光标高度 (调整以适应字体大小) */
		background: linear-gradient(45deg, #ffa20c, #140bfd, #05fded, #ff19fc, #05f900, #f1fd04, #f80411); /* 渐变背景 */
		/* background-color: #abf9c8;*/ /* 或者使用纯色，与文字颜色一致 */ 
		/* 使用 CSS 动画处理闪烁 */
		animation: blink 1s steps(1, start) infinite; /* steps(1, start) 效果更像真实光标 */
	}

	/* 通过 :class 控制动画播放状态 (虽然默认就是 running) */
	.cursor.blink {
		animation-play-state: running;
	}

	/* 光标闪烁动画 */
	@keyframes blink {

		0%,
		100% {
			opacity: 1; /* 显示 */
		}

		50% {
			opacity: 0; /* 隐藏 */
		}
	}
</style>